﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
#include<list>
#include<deque>

using namespace std;

namespace zyt
{
	//template<class T>
	//class vector
	//{};
	// stack和vector的关系，既符合is-a，也符合has-a
	template<class T>
	class stack : public std::vector<T>
	{
	public:
		void push(const T& x)
		{
			// 基类是类模板时，需要指定⼀下类域，
			// 否则编译报错:error C3861: “push_back”: 找不到标识符
			// 因为stack<int>实例化时，也实例化vector<int>了(构造函数实例化了)
			// 但是模版是按需实例化，push_back等成员函数未实例化，所以找不到
			vector<T>::push_back(x);
			//push_back(x);
		}
		void pop()
		{
			vector<T>::pop_back();
		}
		const T& top()
		{
			return vector<T>::back();
		}
		bool empty()
		{
			return vector<T>::empty();
		}
	};
}
int main()
{
	zyt::stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	return 0;
}


//用继承实现栈我们可以定义宏来方便使用多种容器继承
//#define CONTAINER std::vector
//#define CONTAINER std::list
#define CONTAINER std::deque

namespace zyt
{
	template<class T>
	class stack : public CONTAINER<T>
	{
	public:
		void push(const T& x)
		{
			CONTAINER<T>::push_back(x);
		}
		void pop()
		{
			CONTAINER<T>::pop_back();
		}
		const T& top()
		{
			return CONTAINER<T>::back();
		}
		bool empty()
		{
			return CONTAINER<T>::empty();
		}
	};
}
int main()
{
	zyt::stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	while (!st.empty())
	{
		cout << st.top() << " ";
		st.pop();
	}
	return 0;
}

class Person
{
public:
	string _name; // 姓名
	string _sex; // 性别
	int _age; // 年龄
};
class Student : public Person
{
public:
	int _No; // 学号
};
//int main()
//{
//	Student sobj;
//	// 1.派生类对象可以赋值给基类的赋值/指针/引用
//	Person pobj = sobj;//通过调用基类的拷贝构造完成的
//
//	Person* pp = &sobj;//指向子类中切出来的父类的部分
//	Person& rp = sobj;
//	rp._age = 10;//子类可以修改父类
//	
//	//上述&不产生临时对象
//	int a = 0;
//	//double& b = a;
//	//error:产生了临时对象,而临时对象具有常性(这里引用的是临时对象),发生了权限放大，所以要用const修饰
//	const double& b = a;
//	
//	//2.基类对象不能赋值给派生类对象，但是指针/引用强转后可以
//	//sobj = (Student)pobj;
//	Student* ps = (Student*)pp;
//
//	return 0;
//}


class Person
{
public:
	Person(const char* name = "peter")
		 : _name(name)
		{
			cout << "Person()" << endl;
		}
	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}
	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)
			_name = p._name;
		return *this;
	}
	~Person()
	{
		cout << "~Person()" << endl;
	}
protected:
	string _name; // 姓名
};
class Student : public Person
{
public:
	Student(const char* name, int num)
		: Person(name)// 当父类没有可用的默认构造时,显示调用(与构造匿名函数类似)
		, _num(num)
	{
		cout << "Student()" << endl;
	}
	// 严格是不用写的默认生成的就足够，但当需要进行资源的深拷贝时，就得显示实现
	Student(const Student& s)
		: Person(s)// 没有给父类成员的参数，用到父类和子类对象赋值兼容转换
		, _num(s._num)
	{
		cout << "Student(const Student& s)" << endl;
	}
	// 需要深拷贝才实现
	Student& operator = (const Student& s)
	{
		cout << "Student& operator= (const Student& s)" << endl;
		if (this != &s)
		{
			// 构成隐藏，所以需要显⽰调⽤
			Person::operator =(s);//切片
			_num = s._num;
		}
		return *this;
	}
	
	// 需要释放资源才实现
	~Student()
	{
		// 子类的析构与父类的析构构成隐藏关系(编译器会对所有的析构函数名特殊处理成destructor()...)
		// 规定：不需要显示多用，子类析构之后，会自动调用父类析构
		// 这样可以保证析构顺序是先子后父(后定义的要先析构)
		// 若是显示调用了，就取决于实现的人
		//Person::~Person();
		cout << "~Student()" << endl;
	}
protected:
	int _num; // 学号
};
int main()
{
	Student s1("jack", 18);
	Student s2(s1);
	Student s3("rose", 17);
	s1 = s3;
	return 0;
}